//
//  VRViewController.swift
//  VPai
//
//  Created by vicyuan on 16/12/6.
//  Copyright © 2016年 viatech. All rights reserved.
//

import Foundation
import CoreMotion
import GLKit
import player360


private let TAG = "VRViewCtrl"


class VRViewController : GLKViewController, UIActionSheetDelegate, LocalSettingListener, AnimationCallback {
    static let deviceInfo = GBDeviceInfo()
    let ppi = Float(deviceInfo.displayInfo.pixelsPerInch)
    var context : EAGLContext!
    var vrDelegate : VRRender?
    var file : MediaFile!
    
    var motionManager = CMMotionManager()

    var lastScaleFactor : CGFloat! = 1 //放大、缩小
    var netRotation : CGFloat = 1 //旋转
    var netTranslation : CGPoint = CGPoint() //平移
    var resetFramesTimer : NSTimer?
    
    var rotationMatrix : [Float] = [Float](count: 16, repeatedValue: 0)
    var orientation : [Float] = [Float](count: 3, repeatedValue: 0)
    
    let mX = [ 1.0, 0.0, 0.0, 0.0,
               0.0, cosf(Float(M_PI_2)), sinf(Float(M_PI_2)), 0.0,
               0.0, -sinf(Float(M_PI_2)), cosf(Float(M_PI_2)), 0.0,
               0.0, 0.0, 0.0, 1.0 ]
    let mY = [ cosf(Float(M_PI_2)), 0.0, -sinf(Float(M_PI_2)), 0.0,
               0.0, 1.0, 0.0, 0.0,
               sinf(Float(M_PI_2)), 0.0, cosf(Float(M_PI_2)), 0.0,
               0.0, 0.0, 0.0, 1.0 ]
    let mMinusY = [ cosf(Float(-M_PI_2)), 0.0, -sinf(Float(-M_PI_2)), 0.0,
               0.0, 1.0, 0.0, 0.0,
               sinf(Float(-M_PI_2)), 0.0, cosf(Float(-M_PI_2)), 0.0,
               0.0, 0.0, 0.0, 1.0 ]
    let mZ = [ cosf(Float(M_PI_2)), sinf(Float(M_PI_2)), 0.0, 0.0,
               -sinf(Float(M_PI_2)), cosf(Float(M_PI_2)), 0.0, 0.0,
               0.0, 0.0, 1.0, 0.0,
               0.0, 0.0, 0.0, 1.0 ]
    
    deinit {
        if self.context == nil {
            return
        }
        
        LocalSetting.shareInstance.unresistLocalSettingListener(self)
        
        if EAGLContext.currentContext() == self.context {
            vrDelegate?.OnRendererDestroy(self.context)
            EAGLContext.setCurrentContext(nil)
        }
      //  Log.info(TAG, "deinit %@", self.context)
        self.context = nil
    }
    
    func setVRDelegate(d : VRRender?) {
        vrDelegate = d
    }
   
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.preferredFramesPerSecond = 30
        self.context = EAGLContext(API: EAGLRenderingAPI.OpenGLES2)
        
        if (self.context == nil) {
           // Log.info(TAG, msg: "Failed to initialize OpenGLES 2.0 context!")
            exit(1)
        }
        
        if (!EAGLContext.setCurrentContext(self.context)) {
           // Log.info(TAG, msg: "Failed to set current OpenGL context!")
            exit(1)
        }
        
        let v : GLKView = self.view as! GLKView
        
        v.context = self.context;
        v.drawableDepthFormat = .Format24
        v.drawableColorFormat = .RGBA8888
        v.drawableStencilFormat = .Format8
        
        // 双击
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(VRViewController.handleTapGesture(_:)))
        tapGesture.numberOfTapsRequired = 2
        self.view.addGestureRecognizer(tapGesture)
        
        // 缩放
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(VRViewController.handlePinchGesture(_:)))
        self.view.addGestureRecognizer(pinchGesture)
        
        // 旋转
        let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(VRViewController.handleRotateGesture(_:)))
        self.view.addGestureRecognizer(rotateGesture)
        
        // 拖动
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(VRViewController.handlePanGesture(_:)))
        self.view.addGestureRecognizer(panGesture)

        // 长按
        /*let longpressGesutre = UILongPressGestureRecognizer(target: self, action: #selector(VRViewController.handleLongpressGesture(_:)))
        longpressGesutre.minimumPressDuration = 1
        longpressGesutre.allowableMovement = 15
        longpressGesutre.numberOfTouchesRequired = 1
        self.view.addGestureRecognizer(longpressGesutre)*/
        
        // v.delegate = self     no need this as this is default behaveous
        
       // Log.info(TAG, "viewDidLoad ok, %@", self.view)
        
        //FIXME:
        let k = VRRender(ppi: ppi) //AAAARender()   //VRRender()
        self.setVRDelegate(k)

//        Log.debug(TAG, "OnRendererCreated %@", self.context)
        
        vrDelegate?.OnRendererCreated(self.context)
        GLHelpers.checkGlError("VRViewController.viewDidLoad")
        
        LocalSetting.shareInstance.resistLocalSettingListener(self)
        
        var on = LocalSetting.shareInstance.playerVROn
        vrDelegate!.setVirtualReality(on)
        
        let mode = LocalSetting.shareInstance.displayMode
        vrDelegate!.initRenderMode(mode)
        
        vrDelegate!.setAnimationCallback(self)
        
        on = LocalSetting.shareInstance.playerGsensorOn
        if on {
            startDeviceMotion()
        }else {
            stopDeviceMotion()
        }
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        if self.context == nil {
            return
        }
        
        if !EAGLContext.setCurrentContext(self.context) {
            return
        }
        
        let scale = GLHelpers.getScreenScale()

        let width = GLfloat(self.view.bounds.size.width * scale)
        let height = GLfloat(self.view.bounds.size.height * scale)
        
       // Log.debug(TAG, "onRenderChanged %dx%d", Int(width), Int(height))
        vrDelegate?.OnRendererChanged(self.context, width:width, height:height)
        
        GLHelpers.checkGlError("VRViewController.OnRendererChanged")
    }
    
    func OnAnimationStart() {
        self.preferredFramesPerSecond = 60
    }
    
    func OnAnimationEnd() {
        self.preferredFramesPerSecond = 30
    }
    
    func handleTapGesture(sender: UITapGestureRecognizer) {
        //Log.debug(TAG, "handleTapGesture")
        var mode = LocalSetting.shareInstance.displayMode
        mode += 1
        mode %= SUM_MODE
        LocalSetting.shareInstance.displayMode = mode
    }
    
    func handlePinchGesture(sender: UIPinchGestureRecognizer){
        if !LocalSetting.shareInstance.playerTouchOn {
            return
        }
        
        let factor = sender.scale
        //Log.debug(TAG, "handlePinchGesture: scale=\(factor)")
        
        if sender.state == UIGestureRecognizerState.Began {
            lastScaleFactor = factor
            self.preferredFramesPerSecond = 60
        }
        
        if sender.state == UIGestureRecognizerState.Ended {
            self.preferredFramesPerSecond = 30
        }
        
        vrDelegate!.onScale(Float(factor/lastScaleFactor))
        lastScaleFactor = factor
    }
    
    func handleRotateGesture(sender: UIRotationGestureRecognizer) {
        if !LocalSetting.shareInstance.playerTouchOn {
            return
        }
        
        let rotation : CGFloat = sender.rotation
        //Log.debug(TAG, "handleRotateGesture: rotation=\(rotation)")
        
        if sender.state == UIGestureRecognizerState.Began {
            self.preferredFramesPerSecond = 60
        }
        
        if sender.state == UIGestureRecognizerState.Ended {
            netRotation += rotation
            self.preferredFramesPerSecond = 30
        }
    }
    
    func handlePanGesture(sender: UIPanGestureRecognizer) {
        if !LocalSetting.shareInstance.playerTouchOn {
            return
        }
        
        let translation : CGPoint = sender.translationInView(self.view)
        //Log.debug(TAG, "handlePanGesture: translation=\(translation.x), \(translation.y)")
        
        if sender.state == UIGestureRecognizerState.Began {
            netTranslation.x = translation.x
            netTranslation.y = translation.y
            self.preferredFramesPerSecond = 60
        }
        
        if sender.state == UIGestureRecognizerState.Ended {
            self.preferredFramesPerSecond = 30
            
            let velocity = sender.velocityInView(self.view)
            let vx: Float!
            let vy: Float!
            if (motionManager.deviceMotionActive) {
                let sin = sinf(orientation[1])
                let cos = cosf(orientation[1])
                vx = (Float(velocity.x) * cos + Float(velocity.y) * sin)
                vy = (Float(velocity.y) * cos - Float(velocity.x) * sin)
            } else {
                vx = Float(velocity.x)
                vy = Float(velocity.y)
            }
            
            vrDelegate!.onFling(vx, velocityY: -vy)
        } else {
            let dx = Float(translation.x - netTranslation.x)
            let dy = Float(translation.y - netTranslation.y)
            
            let deltaX: Float!
            let deltaY: Float!
            if (motionManager.deviceMotionActive) {
                let sin = sinf(orientation[1])
                let cos = cosf(orientation[1])
                deltaX = (dx * cos + dy * sin)
                deltaY = (dy * cos - dx * sin)
            } else {
                deltaX = dx
                deltaY = dy
            }

            vrDelegate!.onScroll(deltaX, deltaY: -deltaY)
        }
        
        netTranslation.x = translation.x
        netTranslation.y = translation.y
    }
    
    func handleLongpressGesture(sender : UILongPressGestureRecognizer){
        //Log.debug(TAG, "handleLongpressGesture")
        
        if sender.state == UIGestureRecognizerState.Began {
            //vrDelegate!.setVirtualReality()
            
            if !motionManager.deviceMotionActive {
                startDeviceMotion()
            } else {
                stopDeviceMotion()
            }
        }
    }
    
    func startDeviceMotion() {
        motionManager.deviceMotionUpdateInterval = 1.0 / 30.0
        motionManager.gyroUpdateInterval = 1.0 / 30.0
        motionManager.showsDeviceMovementDisplay = true
        
        let motionQueue = NSOperationQueue()
        
        weak var weakself = self
        motionManager.startDeviceMotionUpdatesToQueue(motionQueue, withHandler: {
            (motionData, error) in
            if let strong = weakself {
                let attitude = motionData?.attitude
                let quaternion = attitude?.quaternion
                let tmpQuaternion: [Float] = [
                    Float((quaternion?.w)!),
                    Float((quaternion?.x)!),
                    Float((quaternion?.y)!),
                    Float((quaternion?.z)!)
                ]

                Matrix.getRotationMatrixFromQuaternion(tmpQuaternion, values: &strong.rotationMatrix)
                
                let orientation: UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
                switch (orientation) {
                case UIInterfaceOrientation.LandscapeRight:
                    Matrix.multiplyMM(&strong.rotationMatrix, resultOffset: 0, lhs: strong.mMinusY, lhsOffset: 0, rhs: strong.rotationMatrix, rhsOffset: 0)
                    break
                case UIInterfaceOrientation.LandscapeLeft:
                    Matrix.multiplyMM(&strong.rotationMatrix, resultOffset: 0, lhs: strong.mY, lhsOffset: 0, rhs: strong.rotationMatrix, rhsOffset: 0)
                    Matrix.remapCoordinateSystem(strong.rotationMatrix, X: AXIS_MINUS_X, Y: AXIS_MINUS_Y, outR: &strong.rotationMatrix)
                    break
                case UIInterfaceOrientation.Portrait:
                    Matrix.multiplyMM(&strong.rotationMatrix, resultOffset: 0, lhs: strong.mX, lhsOffset: 0, rhs: strong.rotationMatrix, rhsOffset: 0)
                    Matrix.remapCoordinateSystem(strong.rotationMatrix, X: AXIS_MINUS_Y, Y: AXIS_X, outR: &strong.rotationMatrix)
                    break
                case UIInterfaceOrientation.PortraitUpsideDown://not support now
                    break
                case UIInterfaceOrientation.Unknown:
                    break
                }
                Matrix.getOrientation(strong.rotationMatrix, values: &strong.orientation)
                
                strong.vrDelegate?.onSensor(0, orientation: strong.orientation)
            }
        })
        vrDelegate?.onSensor(1, orientation: nil)
    }
    
    func stopDeviceMotion() {
        motionManager.stopDeviceMotionUpdates()
        vrDelegate?.onSensor(-1, orientation: nil)
    }
    
    func onPlayerGsensorOnChange(){
        let on = LocalSetting.shareInstance.playerGsensorOn
        if on {
            startDeviceMotion()
        }else {
            stopDeviceMotion()
        }
    }
    
    func onPlayerTouchOnChange(){
        
    }
    
    func onPlayerVROnChange(){
        let on = LocalSetting.shareInstance.playerVROn
        vrDelegate!.setVirtualReality(on)
    }
    
    func onDisplayModeChange(){
        let mode = LocalSetting.shareInstance.displayMode
        vrDelegate!.setRenderMode(mode)
        //startResetFramesTimer()
    }
    
    private func startResetFramesTimer() {
        self.preferredFramesPerSecond = 60
        resetFramesTimer?.invalidate()
        resetFramesTimer = nil
        resetFramesTimer = NSTimer.scheduledTimerWithTimeInterval(Double(VRRender.ANIMATION_DURATION)/1000, target: self,selector: #selector(VRViewController.resetFrames(_:)), userInfo: nil, repeats: false)
    }
    
    func resetFrames(t: NSTimer) {
        self.preferredFramesPerSecond = 30
        resetFramesTimer?.invalidate()
        resetFramesTimer = nil
    }
}
                
    
